/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.action.retrievedefault;

import com.inspur.edp.bef.api.action.VoidActionResult;
import com.inspur.edp.bef.api.action.assembler.IBEActionAssembler;
import com.inspur.edp.bef.api.action.assembler.IDefaultValueProcessor;
import com.inspur.edp.bef.api.be.IBEContext;
import com.inspur.edp.bef.api.be.IBusinessEntity;
import com.inspur.edp.bef.api.exceptions.BefException;
import com.inspur.edp.bef.api.exceptions.ErrorCodes;
import com.inspur.edp.bef.core.action.AuthorityUtil;
import com.inspur.edp.bef.core.action.base.ActionUtil;
import com.inspur.edp.bef.core.be.BENodeEntity;
import com.inspur.edp.bef.core.be.BusinessEntity;
import com.inspur.edp.bef.core.be.CoreBEContext;
import com.inspur.edp.bef.core.session.FuncSession;
import com.inspur.edp.bef.core.session.FuncSessionManager;
import com.inspur.edp.bef.entity.exception.ExceptionLevel;
import com.inspur.edp.bef.spi.action.AbstractAction;
import com.inspur.edp.bef.spi.action.assembler.entityAssemblerFactory.IDefaultEntityActionAssFactory;
import com.inspur.edp.bef.spi.entity.CodeRuleInfo;
import com.inspur.edp.bef.spi.event.retrievedefault.BefRetrieveDefaultBroker;
import com.inspur.edp.cdp.coderule.api.CodeRuleBEAssignService;
import com.inspur.edp.cdp.coderule.api.CodeRuleBEService;
import com.inspur.edp.cdp.coderule.api.CodeRuleService;
import com.inspur.edp.cef.entity.accessor.entity.IEntityAccessor;
import com.inspur.edp.cef.entity.changeset.AddChangeDetail;
import com.inspur.edp.cef.entity.entity.IEntityData;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.util.HashMap;
import java.util.Map;

public class RetrieveDefaultAction extends AbstractAction<VoidActionResult> {
    private java.util.Map<String, Object> defaultValues;

    public RetrieveDefaultAction(java.util.Map<String, Object> defaultValues) {
        this.defaultValues = defaultValues;
    }

    @Override
    public void execute() {
        AuthorityUtil.checkDataAuthority(ActionUtil.getBEContext(this));

        BusinessEntity be = ActionUtil.getRootEntity(this);
        if (be.getBEContext().hasData()) {
            throw new BefException(ErrorCodes.InvalidRecreation, "不能使用相同主键重复新增数据", null, ExceptionLevel.Error);
        }

        IEntityData ed = be.createEntityData(be.getID());

        IEntityData currData = (IEntityData) be.getBEContext().getBufferChangeManager().createCurrentBuffer(ed);
        be.getBEContext().setCurrentData(currData);
        dealDefaultValueAndCodeRule(be);
        be.getBEContext().startChangeListener();
        be.getBEContext().appendTempCurrentChange(new AddChangeDetail(currData));
        executeDetermination();
        be.getBEContext().acceptListenerChange();
    }

    private  void  dealDefaultValueAndCodeRule(BusinessEntity be){
        try {
            BefRetrieveDefaultBroker.fireBeforeDealDefaultValue(be,defaultValues, ActionUtil.getBEContext(this).getCurrentData());
            assignDefaultValue(be);
            assignIntroducedValue();
            assignCode(be);
            BefRetrieveDefaultBroker.fireAfterDealDefaultValue(be,defaultValues,ActionUtil.getBEContext(this).getCurrentData());
        } catch (Exception e){
            BefRetrieveDefaultBroker.fireExceptionStop(e);
            throw new RuntimeException(e);
        }
    }
  private void assignIntroducedValue() {
        if (defaultValues == null || defaultValues.isEmpty()) {
            return;
        }

        IEntityAccessor entityAccessor = (IEntityAccessor) ActionUtil.getBEContext(this)
            .getCurrentData();
        IEntityData data = (IEntityData) entityAccessor.getInnerData();

         for (Map.Entry<String, Object> pair : defaultValues.entrySet()) {
          data.setValue(pair.getKey(), pair.getValue());
         }
         if (!ActionUtil.getBEContext(this).getID().equals(data.getID())) {
            throw new IllegalArgumentException("默认值中不能包含主键");
         }
        entityAccessor.setInnerData(data);
    }

    //private void setDefaultValue()
    //{
    //    var accessor = (IEntityAccessor)CoreBEContext.CurrentData;
    //    GetDefaultValueProcessor(this.getBEContext()).setValue(accessor.NodeCode,
    //        (IEntityData)accessor.InnerData);
    //    if (defaultValues != null)
    //    {
    //        foreach (var pair in defaultValues)
    //            CoreBEContext.CurrentData.setValue(pair.Key, pair.Value);
    //        if (!string.equals(CoreBEContext.CurrentData.ID, CoreBEContext.ID))
    //            throw new ArgumentException("默认值中不能包含主键");
    //    }
    //}

    private void executeDetermination() {
        ActionUtil.getRootEntity(this).retrieveDefaultDeterminate();
        //var dtmContext = CoreBEContext.createDeterminationContext();
        //var com.inspur.edp.bef.core.action = new ActionFactory().getRetrieveDefaultDtmAction(dtmContext);
        //com.inspur.edp.bef.core.action.do();
    }

    @Override
    protected IBEActionAssembler getAssembler() {
        return GetAssemblerFactory().getRetrieveDefaultActionAssembler((IBEContext) this.getBEContext());
    }

    public static IDefaultValueProcessor getDefaultValueProcessor(IBEContext context) {
      FuncSession currentSession = ((CoreBEContext)context).getSessionItem().getFuncSession();
      IDefaultValueProcessor processor = currentSession.getDefaultValueProcessor();
        if (processor == null) {
            Object tempVar = context.getBizEntity().getAssemblerFactory();
            IDefaultEntityActionAssFactory factory = (IDefaultEntityActionAssFactory) ((tempVar instanceof IDefaultEntityActionAssFactory) ? tempVar : null);
            if (factory != null) {
                currentSession.setDefaultValueProcessor(processor = (((factory.getDefaultValueProcessor(null))) != null) ? (factory.getDefaultValueProcessor(null)) : new InnerDefaultValueProcessor());
            }
        }
        return processor;
    }

    private void assignDefaultValue(BusinessEntity be) {
//        IEntityAccessor accessor = (IEntityAccessor) be.getBEContext().getCurrentData();
//        IEntityData data = (IEntityData) accessor.getInnerData();
        be.assignDefaultValue(be.getBEContext().getCurrentData());

        // string nodeCode = accessor.NodeCode;
        // var dic = com.inspur.edp.bef.core.be.getDefaultValueDic();
        // if (dic == null)
        //     return;
        // var record = new Dictionary<string, string>();
        // if (nodeCode.equals("RootNode"))
        //     nodeCode = com.inspur.edp.bef.core.be.BEType;
        // if (dic.DefaultValues.containsKey(nodeCode))
        //     record = dic.DefaultValues[nodeCode];
        // else if (dic.DefaultValues.containsKey("RootNode"))
        //     record = dic.DefaultValues["RootNode"];
        // else
        //     return;
        //// var data = accessor.InnerData;
        // PropertyInfo[] info=data.getType().getProperties();
        //foreach(var pi in info)
        //{
        //   if(record.containsKey(pi.Name))
        //    {
        //        if (pi.PropertyType.Name.equals("String"))
        //            pi.setValue(data, record[pi.Name]);
        //        if (pi.PropertyType.Name.equals("Int32"))
        //            pi.setValue(data, Convert.toInt32(record[pi.Name]));
        //        if (pi.PropertyType.Name.equals("Boolean"))
        //            pi.setValue(data, Convert.toBoolean(record[pi.Name]));
        //        if (pi.PropertyType.Name.equals("Decimal"))
        //            pi.setValue(data,Convert.toDecimal(record[pi.Name]));
        //        if (pi.PropertyType.Name.equals("DateTime"))
        //            pi.setValue(data,Convert.toDateTime(record[pi.Name]));
        //        if (pi.PropertyType.BaseType == typeof(Enum))
        //            pi.setValue(data,Enum.parse(pi.PropertyType,record[pi.Name]));
        //    }
        //}
    }

    private void assignCode(BusinessEntity be) {
        IEntityData data = ActionUtil.getBEContext(this).getCurrentData();
        java.util.HashMap<String, CodeRuleInfo> codeInfo = be.getAfterCreateCodeRule();
        if (codeInfo == null || codeInfo.isEmpty()) {
            return;
        }
        HashMap<String,Object> map=new HashMap<>();
        map.put(be.getNodeCode(),data);
        CodeRuleBEAssignService service = SpringBeanUtils.getBean(CodeRuleBEAssignService.class);
        for (String key : codeInfo.keySet()) {

            String code = service.generate(
                be.getBEContext().getBEManagerContext().getBEManager().getBEInfo().getBEID(),
                be.getNodeCode(),
                key,
                map,
                codeInfo.get(key).getCodeRuleId());
            data.setValue(key, code);
        }
    }
}
